home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
msdos
/
viewers
/
pvquan16
/
quant
/
files.c
next >
Wrap
C/C++ Source or Header
|
1992-11-30
|
11KB
|
347 lines
/************************************************************************
* *
* Copyright (c) 1991, Frank van der Hulst *
* All Rights Reserved *
* *
* Authors: *
* FvdH - Frank van der Hulst (Wellington, NZ) *
* *
* Versions: *
* V1.1 910626 FvdH - QUANT released for DBW_RENDER *
* V1.2 911021 FvdH - QUANT released for PoV Ray *
* V1.3 911030 FvdH - Added 320x200x256x4 pages support *
* - Fixed bug in output_anim_files *
* V1.4 920303 FvdH - Ported to GNU C *
* V1.5 920331 FvdH - Allow Targa input *
* 920403 FvdH - Allow any number of files *
* V1.6 921023 FvdH - Produce multi-image GIFs *
* - Port to OS/2 IBM C Set/2 *
* *
************************************************************************/
#include <string.h>
#ifdef __TURBOC__
#include <dos.h>
#define SC_INDEX 0x3c4
#define MAP_MASK 2
#endif
#ifdef __GNUC__
#define SEEK_SET 0
#endif
#include "gif_lib.h"
#include "quant.h"
int (*get_pixel)(UCHAR *pixel);
static FILE *out_file;
static FILE *in_file[3];
static int get_pixel_raw(UCHAR *pixel)
{
int t;
#if INPUT_BITS == 8
if ((t = getc(in_file[2])) == EOF) return FALSE;
pixel[BLUE] = t;
if ((t = getc(in_file[1])) == EOF) return FALSE;
pixel[GREEN] = t;
if ((t = getc(in_file[0])) == EOF) return FALSE;
pixel[RED] = t;
#else
#define MAX_IN ((0xff << (8 - INPUT_BITS)) & 0xff)
#define ROUND (1 << (7 - INPUT_BITS))
#define R_SHIFT (8 - INPUT_BITS)
if ((t = getc(in_file[2])) == EOF) return FALSE;
pixel[BLUE] = t < MAX_IN ? (t + ROUND) >> R_SHIFT : t >> R_SHIFT;
if ((t = getc(in_file[1])) == EOF) return FALSE;
pixel[GREEN] = t < MAX_IN ? (t + ROUND) >> R_SHIFT : t >> R_SHIFT;
if ((t = getc(in_file[0])) == EOF) return FALSE;
pixel[RED] = t < MAX_IN ? (t + ROUND) >> R_SHIFT : t >> R_SHIFT;
#undef MAX_IN
#undef ROUND
#undef R_SHIFT
#endif
return TRUE;
}
static int get_pixel_targa(UCHAR *pixel)
{
int t;
#if INPUT_BITS == 8
if ((t = getc(in_file[0])) == EOF) return FALSE;
pixel[BLUE] = t;
if ((t = getc(in_file[0])) == EOF) return FALSE;
pixel[GREEN] = t;
if ((t = getc(in_file[0])) == EOF) return FALSE;
pixel[RED] = t;
#else
#define MAX_IN ((0xff << (8 - INPUT_BITS)) & 0xff)
#define ROUND (1 << (7 - INPUT_BITS))
#define R_SHIFT (8 - INPUT_BITS)
if ((t = getc(in_file[0])) == EOF) return FALSE;
pixel[BLUE] = t < MAX_IN ? (t + ROUND) >> R_SHIFT : t >> R_SHIFT;
if ((t = getc(in_file[0])) == EOF) return FALSE;
pixel[GREEN] = t < MAX_IN ? (t + ROUND) >> R_SHIFT : t >> R_SHIFT;
if ((t = getc(in_file[0])) == EOF) return FALSE;
pixel[RED] = t < MAX_IN ? (t + ROUND) >> R_SHIFT : t >> R_SHIFT;
#undef MAX_IN
#undef ROUND
#undef R_SHIFT
#endif
return TRUE;
}
/* The "+ft" option of PVRAY writes out Targa format. Specifically, the
fields are:
Header:
00 00 02 00 00 - Fixed header information for uncompressed type 2 image
00 00 00
0000 - Horizontal offset always is at 0000
llll - Vertical offset (1st line number, 16 bits, LSB first)
wwww hhhh - width, height of image (16 bits each, LSB first)
18 20 - 24 bits per pixel, Top-down raster
For each line:
bb gg rr bb gg rr ... - blue, green, and red data, 8 bits for each pixel.
*/
void open_file(char *fname, int num)
{
char filename[256];
if (input_type == 0) {
sprintf(filename, "%s_%d.red", fname, num);
if ((in_file[0] = fopen(filename, "rb")) == NULL) {
printf("Cannot open %s.\n", filename);
err_exit();
}
sprintf(filename, "%s_%d.grn", fname, num);
if ((in_file[1] = fopen(filename, "rb")) == NULL) {
printf("Cannot open %s.\n", filename);
err_exit();
}
sprintf(filename, "%s_%d.blu", fname, num);
if ((in_file[2] = fopen(filename, "rb")) == NULL) {
printf("Cannot open %s.\n", filename);
err_exit();
}
get_pixel = get_pixel_raw;
return;
}
if (input_type == 1) {
sprintf(filename, "%s_%d.tga", fname, num);
if ((in_file[0] = fopen(filename, "rb")) == NULL) {
printf("Cannot open %s.\n", filename);
err_exit();
}
fseek(in_file[0], 18, SEEK_SET); /* Skip header */
get_pixel = get_pixel_targa;
return;
}
}
void close_file(void)
{
fclose(in_file[0]);
if (input_type == 0) {
fclose(in_file[1]);
fclose(in_file[2]);
}
}
void write_4_planes(char *infname, int num, UINT Xres, UINT Yres)
{
UINT plane, x, y;
UCHAR pixel[3];
char more_data;
char dummy[3];
#ifdef __TURBOC__
char far *VGA_addr = MK_FP(0xa000,0);
#endif
open_file(infname, num);
for (plane = 0; plane < 4; plane++) {
more_data = 1;
fseek(in_file[0], (long)plane, SEEK_SET);
fseek(in_file[1], (long)plane, SEEK_SET);
fseek(in_file[2], (long)plane, SEEK_SET);
#ifdef __TURBOC__
if (disp_image) outport(SC_INDEX, (0x100 << plane) | MAP_MASK);
#endif
for (y = 0; y < Yres; y++) {
for (x = plane; x < Xres; x += 4) {
if (more_data) {
if (!get_pixel(pixel))
pixel[RED] = pixel[GREEN] = pixel[BLUE] = more_data = 0;
else {
fread(dummy, 3, 1, in_file[0]); /* Skip to next pixel for this plane */
fread(dummy, 3, 1, in_file[1]);
fread(dummy, 3, 1, in_file[2]);
}
putc(pal_index(pixel), out_file);
#ifdef __TURBOC__
if (disp_image) *VGA_addr++ = pal_index(pixel);
#endif
} else putc(pal_index(pixel), out_file);
}
}
}
close_file();
}
static void write_linear(char *infname, int num, UINT Xres, UINT Yres)
{
UINT x, y;
UCHAR pixel[3];
char more_data;
#ifdef __TURBOC__
char far *VGA_addr = MK_FP(0xa000,0);
#endif
open_file(infname, num);
more_data = 1;
for (y = 0; y < Yres; y++) {
for (x = 0; x < Xres; x++) {
if (more_data) {
if (!get_pixel(pixel))
pixel[RED] = pixel[GREEN] = pixel[BLUE] = more_data = 0;
}
putc(pal_index(pixel), out_file);
#ifdef __TURBOC__
if (disp_image) {
outport(SC_INDEX, (0x100 << (x & 3)) | MAP_MASK);
VGA_addr[y*(320/4)+x/4] = pal_index(pixel);
}
#endif
}
}
close_file();
}
/****************************************************************************
Convert Raw image (One byte per pixel) into Gif file. Raw data is read
from in_file, and Gif is dumped to out_fname. ImageWidth times ImageHeight
bytes are read. Color map is dumped from ColorMap.
*/
static void output_gif_file(char *infname, int num_files, char *out_fname, UINT Xres, UINT Yres, UINT num_colours)
{
int i, x, y;
UCHAR pixel[3];
UCHAR *ScanLine;
for (i = 0; i < 8 && (2 << i) < num_colours; i++);
num_colours = 2 << i;
if (num_colours > 256) {
printf("Colour map must be less than 256 colours.\n");
err_exit();
}
printf("\nImage size is %dx%d: ", Xres, Yres);
if (EGifOpenFileName(out_fname) == -1) return;
EGifPutScreenDesc(Xres, Yres, 6, 0, 8, palette);
for (i = 0; i < num_files ; i++) {
open_file(infname, i);
EGifPutImageDesc(0, 0, Xres, Yres, 8);
CHECK_ALLOC(ScanLine, UCHAR, Xres, "Scan Line");
/* Here it is - get one raw line from input file, and dump to Gif: */
for (y = 0; y < Yres; y++) {
/* Note we assume here PixelSize == Byte, which is not necessarily */
/* so. If not - must read one byte at a time, and coerce to pixel. */
for (x = 0; x < Xres; x++) {
if (!get_pixel(pixel)) {
printf("RAW input file ended prematurely.\n");
err_exit();
}
ScanLine[x] = pal_index(pixel);
}
if (EGifPutLine(ScanLine, Xres)) break;
printf("\b\b\b\b%-4d", y);
}
} /* endfor */
EGifCloseFile();
free(ScanLine);
close_file();
}
void output_xd_file(char *infname, int num, char *out_fname, int colors,
int num_files, int Xres, int Yres, int type)
{
int i;
if ((out_file = fopen(out_fname, "wb")) == NULL) {
printf("Couldn't open %s.\n", out_fname);
err_exit();
}
putc(num_files + '1', out_file);
putc('D', out_file);
putw(Xres, out_file);
putw(Yres, out_file);
putc(colors, out_file);
fwrite(palette, 3, colors, out_file);
#ifdef __TURBOC__
if ((Xres != 320) || ((Yres != 200) && (Yres != 400))) disp_image = FALSE;
if (disp_image) {
if (Yres == 200) set320x200x4mode();
else if (Yres == 400) set320x400mode();
setvgapalette(&palette, colors);
}
#endif
for (i = 0; i < num_files; i++)
if (type == 0) write_4_planes(infname, num + i, Xres, Yres);
else write_linear(infname, num + i, Xres, Yres);
fclose(out_file);
#ifdef __TURBOC__
if (disp_image)
if (Yres == 200) end320x200mode();
else end320x400mode();
#endif
}
void output_anim_files(char *infname, char *out_fname,
int colors, int num_files, UINT Xres, UINT Yres, int type)
{
int i;
char outname[256];
for (i = 0; i < num_files; i++) {
sprintf(outname, "%s.%d", out_fname, i);
printf("Outputting to %s\n", outname);
output_xd_file(infname, i, outname, colors, 1, Xres, Yres, type);
}
}
void write_file(int num_files, char *input_file, int Xres, int Yres,
int colors, int output_type)
{
char outfilename[256];
if (num_files > 2)
strcpy(outfilename, input_file);
else if (output_type == 2)
sprintf(outfilename, "%s.gif", input_file);
else
sprintf(outfilename, "%s.%cd", input_file, num_files + '1');
printf("Outputting to %s\n", outfilename);
if (output_type == 2)
output_gif_file(input_file, num_files, outfilename, Xres, Yres, colors);
else if (num_files < 3) {
output_xd_file(input_file, 0, outfilename, colors, num_files, Xres, Yres, output_type);
} else output_anim_files(input_file, outfilename, colors, num_files, Xres, Yres, output_type);
}